package com.cw.frame.codegen;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import com.cw.frame.codegen.parameter.EnumField;
import com.cw.frame.codegen.parameter.Field;
import com.cw.frame.codegen.parameter.PkField;

/**
 * Define the application configuration.
 *
 * @author chenw
 */
public class Configuration {
    @SuppressWarnings("rawtypes")
    private static final ThreadLocal threadConfiguration = new ThreadLocal();
    private static Configuration configuration;
    private static Configuration pageConfiguration;
    private static Configuration classConfiguration;
    private static Configuration jdbcConfiguration;
    /**
     * The database url for jdbc
     */
    private String jdbcUrl;

    /**
     * The jdbc driver class name
     */
    private String driverClass;

    /**
     * User name of the database
     */
    private String dbUserName;

    /**
     * Password of the database
     */
    private String dbPassword;

    /**
     * The java source templates directory
     */
    private String javaTemplatePath;

    /**
     * The java source output directory
     */
    private String javaOutputPath;

    /**
     * The page file (js, jsp) templates directory
     */
    private String pageTemplatePath;

    /**
     * The page file (js, jsp) output directory
     */
    private String pageOutputPath;
    /**
     * The xml file (js, jsp) templates directory
     */
    private String xmlTemplatePath;
    /**
     * The xml file (js, jsp) output directory
     */
    private String xmlOutputPath;
    /**
     * The packages names, separated by comma ','.
     */
    private String packages;

    /**
     * The table names, separated by comma ','.
     */
    private String tableNames;
    /**
     * The entity class names, separated by comma ','.
     */
    private String entityClasses;
    /** 作者 用于註釋 */
    private String author;
    /** 頁面路徑 */
    private String pagePath;
    /** 表中文名 */
    private String tableCnNames;
    /** 模块id */
    private String moduleId;
    /** 模块中文 */
    private String moduleIdCn;
    /** 项目编码 */
    private String projectCode;
    /** 项目类型 */
    private String projectType;
    /** 生成代码模板id */
    private String templateId;
    /** 主键信息 */
    private String pkIds;
    /** 主键数据类型 */
    private String pkIdDataTypes;
    /** 主键集合信息 */
    private List<List<PkField>> pkList = new LinkedList<>();
    /** 枚举信息 */
    private List<EnumField> enumLists = new LinkedList<>();
    /** 表字段信息 */
    private List<List<Field>> fieldList = new LinkedList<>();
    /** 查询字段信息 */
    private List<List<Field>> queryList = new LinkedList<>();
    /** 排序字段信息 */
    private List<List<Field>> orderList = new LinkedList<>();
    /** 列表字段信息 */
    private List<List<Field>> listList = new LinkedList<>();
    /** 表单字段信息 */
    private List<List<Field>> formList = new LinkedList<>();

    @SuppressWarnings("unchecked")
    synchronized public static Configuration getDefault() {

        configuration = (Configuration) threadConfiguration.get();
        if (configuration != null) {
            return configuration;
        } else {
            configuration = new Configuration();
            threadConfiguration.set(configuration);
        }
        Properties properties = new Properties();
        try {
            properties.load(Configuration.class.getResourceAsStream("/codegen.properties"));
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        configuration.setJdbcUrl(properties.getProperty("jdbc.url"));
        configuration.setDriverClass(properties.getProperty("jdbc.driverClassName"));
        configuration.setDbUserName(properties.getProperty("jdbc.username"));
        configuration.setDbPassword(properties.getProperty("jdbc.password"));

        // 设置表信息
        configuration.setEntityClasses(properties.getProperty("frame.code.generate.entity.class"));
        configuration.setTableNames(properties.getProperty("frame.code.generate.table.name"));
        configuration.setModuleId(properties.getProperty("frame.code.generate.module.id"));
        configuration.setPkIds(properties.getProperty("frame.code.generate.table.pId"));
        configuration.setTableCnNames(properties.getProperty("frame.code.generate.table.cnName"));

        // 设置路径
        String absolutePath = properties.getProperty("frame.code.generate.project.absolute.path");
        configuration.setJavaOutputPath(
            properties.getProperty("frame.code.generate.output.java.path", absolutePath + "/generated"));
        configuration.setJavaTemplatePath(
            properties.getProperty("frame.code.generate.template.java.path", absolutePath + "/templates/java"));
        configuration.setPackages(properties.getProperty("frame.code.generate.module.package.name"));
        configuration.setPageOutputPath(
            properties.getProperty("frame.code.generate.output.page.path", absolutePath + "/generated"));
        configuration.setPageTemplatePath(
            properties.getProperty("frame.code.generate.template.page.path", absolutePath + "/templates/page"));
        configuration.setXmlOutputPath(
            properties.getProperty("frame.code.generate.output.xml.path", absolutePath + "/generated"));
        configuration.setXmlTemplatePath(
            properties.getProperty("frame.code.generate.template.xml.path", absolutePath + "/templates/page"));
        configuration.setAuthor(properties.getProperty("frame.code.generate.author.name"));
        configuration.setPagePath(properties.getProperty("frame.code.generate.page.path"));

        return configuration;
    }

    @SuppressWarnings("unchecked")
    synchronized public static Configuration getJdbcConfig() {

        jdbcConfiguration = (Configuration) threadConfiguration.get();
        if (jdbcConfiguration != null) {
            return jdbcConfiguration;
        } else {
            jdbcConfiguration = new Configuration();
            threadConfiguration.set(jdbcConfiguration);
        }
        return jdbcConfiguration;
    }

    /**
     * 封装页面配置信息
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    synchronized public static Configuration getPageConfig() {

        pageConfiguration = (Configuration) threadConfiguration.get();
        if (pageConfiguration != null) {
            return pageConfiguration;
        } else {
            pageConfiguration = new Configuration();
            threadConfiguration.set(pageConfiguration);
        }
        return pageConfiguration;
    }

    /**
     * 封装class配置信息
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    synchronized public static Configuration getClassConfig() {

        classConfiguration = (Configuration) threadConfiguration.get();
        if (classConfiguration != null) {
            return classConfiguration;
        } else {
            classConfiguration = new Configuration();
            threadConfiguration.set(classConfiguration);
        }
        return classConfiguration;
    }

    /**
     * 为了防止内存泄露，使用完需要清理
     * @return
     */
    public static void clean() {
        threadConfiguration.remove();
    }

    /**
     * @return the jdbcUrl
     */
    public String getJdbcUrl() {
        return jdbcUrl;
    }

    /**
     * @param jdbcUrl the jdbcUrl to set
     */
    public void setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
    }

    /**
     * @return the driverClass
     */
    public String getDriverClass() {
        return driverClass;
    }

    /**
     * @param driverClass the driverClass to set
     */
    public void setDriverClass(String driverClass) {
        this.driverClass = driverClass;
    }

    /**
     * @return the dbUserName
     */
    public String getDbUserName() {
        return dbUserName;
    }

    /**
     * @param dbUserName the dbUserName to set
     */
    public void setDbUserName(String dbUserName) {
        this.dbUserName = dbUserName;
    }

    /**
     * @return the dbPassword
     */
    public String getDbPassword() {
        return dbPassword;
    }

    /**
     * @param dbPassword the dbPassword to set
     */
    public void setDbPassword(String dbPassword) {
        this.dbPassword = dbPassword;
    }

    /**
     * @return the javaTemplatePath
     */
    public String getJavaTemplatePath() {
        return javaTemplatePath;
    }

    /**
     * @param javaTemplatePath the javaTemplatePath to set
     */
    public void setJavaTemplatePath(String javaTemplatePath) {
        this.javaTemplatePath = javaTemplatePath;
    }

    /**
     * @return the javaOutputPath
     */
    public String getJavaOutputPath() {
        return javaOutputPath;
    }

    /**
     * @param javaOutputPath the javaOutputPath to set
     */
    public void setJavaOutputPath(String javaOutputPath) {
        this.javaOutputPath = javaOutputPath;
    }

    /**
     * @return the pageTemplatePath
     */
    public String getPageTemplatePath() {
        return pageTemplatePath;
    }

    /**
     * @param pageTemplatePath the pageTemplatePath to set
     */
    public void setPageTemplatePath(String pageTemplatePath) {
        this.pageTemplatePath = pageTemplatePath;
    }

    /**
     * @return the pageOutputPath
     */
    public String getPageOutputPath() {
        return pageOutputPath;
    }

    /**
     * @param pageOutputPath the pageOutputPath to set
     */
    public void setPageOutputPath(String pageOutputPath) {
        this.pageOutputPath = pageOutputPath;
    }

    public String getXmlTemplatePath() {
        return xmlTemplatePath;
    }

    public void setXmlTemplatePath(String xmlTemplatePath) {
        this.xmlTemplatePath = xmlTemplatePath;
    }

    public String getXmlOutputPath() {
        return xmlOutputPath;
    }

    public void setXmlOutputPath(String xmlOutputPath) {
        this.xmlOutputPath = xmlOutputPath;
    }

    /**
     * @return the packages
     */
    public String getPackages() {
        return packages;
    }

    /**
     * @param packages the packages to set
     */
    public void setPackages(String packages) {
        this.packages = packages;
    }

    /**
     * @return the tableNames
     */
    public String getTableNames() {
        return tableNames;
    }

    /**
     * @param tableNames the tableNames to set
     */
    public void setTableNames(String tableNames) {
        this.tableNames = tableNames;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    /**
     * @return the entityClasses
     */
    public String getEntityClasses() {
        return entityClasses;
    }

    /**
     * @param entityClasses the entityClasses to set
     */
    public void setEntityClasses(String entityClasses) {
        this.entityClasses = entityClasses;
    }

    public String getPagePath() {
        return pagePath;
    }

    public void setPagePath(String pagePath) {
        this.pagePath = pagePath;
    }

    public String getTableCnNames() {
        return tableCnNames;
    }

    public void setTableCnNames(String tableCnNames) {
        this.tableCnNames = tableCnNames;
    }

    public String getModuleId() {
        return moduleId;
    }

    public void setModuleId(String moduleId) {
        this.moduleId = moduleId;
    }

    public List<List<Field>> getFieldList() {
        return fieldList;
    }

    public void setFieldList(List<List<Field>> fieldList) {
        this.fieldList = fieldList;
    }

    public List<List<Field>> getQueryList() {
        return queryList;
    }

    public void setQueryList(List<List<Field>> queryList) {
        this.queryList = queryList;
    }

    public List<List<Field>> getOrderList() {
        return orderList;
    }

    public void setOrderList(List<List<Field>> orderList) {
        this.orderList = orderList;
    }

    public List<List<Field>> getListList() {
        return listList;
    }

    public void setListList(List<List<Field>> listList) {
        this.listList = listList;
    }

    public List<List<Field>> getFormList() {
        return formList;
    }

    public void setFormList(List<List<Field>> formList) {
        this.formList = formList;
    }

    public String getTemplateId() {
        return templateId;
    }

    public void setTemplateId(String templateId) {
        this.templateId = templateId;
    }

    public String getPkIds() {
        return pkIds;
    }

    public void setPkIds(String pkIds) {
        this.pkIds = pkIds;
    }

    public List<List<PkField>> getPkList() {
        return pkList;
    }

    public void setPkList(List<List<PkField>> pkList) {
        this.pkList = pkList;
    }

    public String getPkIdDataTypes() {
        return pkIdDataTypes;
    }

    public void setPkIdDataTypes(String pkIdDataTypes) {
        this.pkIdDataTypes = pkIdDataTypes;
    }

    public String getModuleIdCn() {
        return moduleIdCn;
    }

    public void setModuleIdCn(String moduleIdCn) {
        this.moduleIdCn = moduleIdCn;
    }

    public List<EnumField> getEnumLists() {
        return enumLists;
    }

    public void setEnumLists(List<EnumField> enumLists) {
        this.enumLists = enumLists;
    }

    public String getProjectCode() {
        return projectCode;
    }

    public void setProjectCode(String projectCode) {
        this.projectCode = projectCode;
    }

    public String getProjectType() {
        return projectType;
    }

    public void setProjectType(String projectType) {
        this.projectType = projectType;
    }

    /**
     * (non-Javadoc)
     *
     * @see Object#toString()
     */
    @Override
    public String toString() {
        return "Configuration [jdbcUrl=" + jdbcUrl + ", driverClass=" + driverClass + ", dbUserName=" + dbUserName
            + ", dbPassword=" + dbPassword + ", javaTemplatePath=" + javaTemplatePath + ", javaOutputPath="
            + javaOutputPath + ", pageTemplatePath=" + pageTemplatePath + ", pageOutputPath=" + pageOutputPath
            + ", packages=" + packages + ", tableNames=" + tableNames + ", entityClasses=" + entityClasses + "]";
    }

}
